/**
 * 二维向量。
 */
class Vector2 {
   /**
    * X分量。
    */
   public x: number;

   /**
    * Y分量。
    */
   public y: number;

   // /**
   //  * 构造处理。
   //  *
   //  * @certify 210926
   //  * @param x X分量
   //  * @param y Y分量
   //  */
   // public constructor(x?: number, y?: number) {
   //    this.x = x || 0;
   //    this.y = y || 0;
   // }

   // /**
   //  * 获得X分量。
   //  *
   //  * @return X分量
   //  */
   // public get X(): number {
   //    return this.x;
   // }

   // /**
   //  * 获得Y分量。
   //  *
   //  * @return Y分量
   //  */
   // public get Y(): number {
   //    return this.y;
   // }

   // /**
   //  * 获得宽度。
   //  *
   //  * @return 宽度
   //  */
   // public get width(): number {
   //    return this.x;
   // }

   // /**
   //  * 设置宽度。
   //  *
   //  * @param value 宽度
   //  */
   // public set width(value: number) {
   //    this.x = value;
   // }

   // /**
   //  * 获得高度。
   //  *
   //  * @return 高度
   //  */
   // public get height(): number {
   //    return this.y;
   // }

   // /**
   //  * 设置宽度。
   //  *
   //  * @param value 宽度
   //  */
   // public set height(value: number) {
   //    this.y = value;
   // }

   // /**
   //  * 判断是否有效。
   //  *
   //  * @return 有效
   //  */
   // public isValid(): boolean {
   //    return isFinite(this.x) && isFinite(this.y);
   // }

   // /**
   //  * 判断是否为空。
   //  *
   //  * @return 是否为空
   //  */
   // public isEmpty(): boolean {
   //    return (this.x == 0) && (this.y == 0);
   // }

   // /**
   //  * 判断是否为0。
   //  *
   //  * @param tolerance 容差
   //  * @return 是否为0
   //  */
   // public isZero(tolerance: number = MathUtil.TOLERANCE): boolean {
   //    return Vector2.isZero(this, tolerance);
   // }

   // /**
   //  * 判断是否相等。
   //  *
   //  * @param value 数据
   //  * @return 是否相等
   //  */
   // public equals(value: Value2): boolean {
   //    return Vector2.equals(this, value);
   // }

   // /**
   //  * 判断是否为负。
   //  *
   //  * @param value1 内容1
   //  * @param value2 内容2
   //  * @return 是否为负
   //  */
   // public static equalsNegative(value1: Value2, value2: Value2): boolean {
   //    return (value1.x == -value2.x) && (value1.y == -value2.y);
   // }

   // /**
   //  * 判断是否近似相等。
   //  *
   //  * @param value 数据
   //  * @param tolerance 容差
   //  * @return 是否相等
   //  */
   // public nearlyEquals(value: Value2, tolerance: number = MathUtil.TOLERANCE): boolean {
   //    return Vector2.nearlyEquals(this, value, tolerance);
   // }

   // /**
   //  * 判断是否近似相等(距离判定)。
   //  *
   //  * @param value 数据
   //  * @param tolerance 容差
   //  * @return 是否相等
   //  */
   // public nearlyEqualsDistance(value: Value2, tolerance: number = MathUtil.TOLERANCE): boolean {
   //    var dis = Vector2.distance(value, this);
   //    return dis <= tolerance;
   // }

   // /**
   //  * 判断是否近似为负。
   //  *
   //  * @param value1 内容1
   //  * @param value2 内容2
   //  * @param tolerance 容差
   //  * @return 是否为负
   //  */
   // public static nearlyEqualsNegative(value1: Value2, value2: Value2, tolerance: number = MathUtil.TOLERANCE): boolean {
   //    return MathUtil.nearlyEquals(value1.x, -value2.x, tolerance) &&
   //       MathUtil.nearlyEquals(value1.y, -value2.y, tolerance);
   // }

   // /**
   //  * 判断是否相等。
   //  *
   //  * @param x X分量
   //  * @param y Y分量
   //  * @return 是否相等
   //  */
   // public equalsValue(x: number, y: number): boolean {
   //    return (this.x == x) && (this.y == y);
   // }

   // /**
   //  * 判断是否近似相等。
   //  *
   //  * @param x X分量
   //  * @param y Y分量
   //  * @param tolerance 容差
   //  * @return 是否相等
   //  */
   // public nearlyEqualsValue(x: number, y: number, tolerance: number = MathUtil.TOLERANCE): boolean {
   //    var ex = MathUtil.nearlyEquals(this.x, x, tolerance);
   //    var ey = MathUtil.nearlyEquals(this.y, y, tolerance);
   //    return ex && ey;
   // }

   // /**
   //  * 设置X分量。
   //  *
   //  * @param x X分量
   //  * @return 向量
   //  */
   // public setX(x: number): Vector2 {
   //    this.x = x;
   //    return this;
   // }

   // /**
   //  * 设置Y分量。
   //  *
   //  * @param y Y分量
   //  * @return 向量
   //  */
   // public setY(y: number): Vector2 {
   //    this.y = y;
   //    return this;
   // }

   // /**
   //  * 设置数据。
   //  *
   //  * @certify 220511
   //  * @param x X分量
   //  * @param y Y分量
   //  * @return 向量
   //  */
   // public set(x: number, y: number): Vector2 {
   //    this.x = x;
   //    this.y = y;
   //    return this;
   // }

   // /**
   //  * 设置数据。
   //  *
   //  * @param value 数据
   //  * @return 向量
   //  */
   // public setScalar(value: number): Vector2 {
   //    this.x = value;
   //    this.y = value;
   //    return this;
   // }

   // /**
   //  * 获得组件内容。
   //  *
   //  * @param index 索引
   //  * @return 数据
   //  */
   // public getComponent(index: number): number {
   //    switch (index) {
   //       case 0:
   //          return this.x;
   //       case 1:
   //          return this.y;
   //       default:
   //          throw new Fatal(this, 'Invalid component index.');
   //    }
   // }

   // /**
   //  * 设置组件内容。
   //  *
   //  * @param index 索引
   //  * @param value 数据
   //  */
   // public setComponent(index: number, value: number): void {
   //    switch (index) {
   //       case 0:
   //          this.x = value;
   //          break;
   //       case 1:
   //          this.y = value;
   //          break;
   //       default:
   //          throw new Fatal(this, 'Invalid component index.');
   //    }
   // }

   // /**
   //  * 接收数据。
   //  *
   //  * @param value 数据
   //  * @return 向量
   //  */
   // public assign(value: Value2): Vector2 {
   //    this.x = value.x;
   //    this.y = value.y;
   //    return this;
   // }

   // /**
   //  * 复制数据。
   //  *
   //  * @param value 数据
   //  * @return 向量
   //  */
   // public copy(value: Value2): Vector2 {
   //    this.x = value.x;
   //    this.y = value.y;
   //    return this;
   // }

   // /**
   //  * 数据相加处理。
   //  *
   //  * @param value 数据
   //  * @return 向量
   //  */
   // public addScalar(value: number): Vector2 {
   //    this.x += value;
   //    this.y += value;
   //    return this;
   // }

   // /**
   //  * 单个数据相加处理。
   //  *
   //  * @param value 数据
   //  * @return 向量
   //  */
   // public add(value: Value2): Vector2 {
   //    this.x += value.x;
   //    this.y += value.y;
   //    return this;
   // }

   // /**
   //  * 单个数据相加处理。
   //  *
   //  * @param value 数据
   //  * @return 向量
   //  */
   // public addTo(value: Value2): Vector2 {
   //    var ref = new Vector2();
   //    ref.x = this.x + value.x;
   //    ref.y = this.y + value.y;
   //    return ref;
   // }

   // /**
   //  * 分量数据相加处理。
   //  *
   //  * @param x X分量
   //  * @param y Y分量
   //  * @return 向量
   //  */
   // public addValue(x: number, y: number): Vector2 {
   //    this.x += x;
   //    this.y += y;
   //    return this;
   // }

   // /**
   //  * 比率数据相加处理。
   //  *
   //  * @param value 数据
   //  * @param scale 比率
   //  * @return 向量
   //  */
   // public addScaledVector(value: Value2, scale: number): Vector2 {
   //    this.x += value.x * scale;
   //    this.y += value.y * scale;
   //    return this;
   // }

   // /**
   //  * 多个数据相加处理。
   //  *
   //  * @param value1 数据1
   //  * @param value2 数据2
   //  * @return 向量
   //  */
   // public addVectors(value1: Value2, value2: Value2): Vector2 {
   //    this.x = value1.x + value2.x;
   //    this.y = value1.y + value2.y;
   //    return this;
   // }

   // /**
   //  * 多个数据相加处理。
   //  *
   //  * @param value1 数据1
   //  * @param value2 数据2
   //  * @param ref
   //  * @return 向量
   //  */
   // public static addVector(value1: Value2, value2: Value2, ref?: Vector2): Vector2 {
   //    ref = ref || new Vector2();
   //    ref.x = value1.x + value2.x;
   //    ref.y = value1.y + value2.y;
   //    return ref;
   // }

   // /**
   //  * 数据相减处理。
   //  *
   //  * @param value 数据
   //  * @return 向量
   //  */
   // public subScalar(value: number): Vector2 {
   //    this.x -= value;
   //    this.y -= value;
   //    return this;
   // }

   // /**
   //  * 单个数据相减处理。
   //  *
   //  * @param value 数据
   //  * @return 向量
   //  */
   // public sub(value: Value2): Vector2 {
   //    this.x -= value.x;
   //    this.y -= value.y;
   //    return this;
   // }

   // /**
   //  * 分量数据相减处理。
   //  *
   //  * @param x X分量
   //  * @param y Y分量
   //  * @return 向量
   //  */
   // public subValue(x: number, y: number): Vector2 {
   //    this.x -= x;
   //    this.y -= y;
   //    return this;
   // }

   // /**
   //  * 多个数据相减处理。
   //  *
   //  * @param value 内容
   //  * @return 向量
   //  */
   // public subTo(value: Value2): Vector2 {
   //    var ref = new Vector2();
   //    ref.x = this.x - value.x;
   //    ref.y = this.y - value.y;
   //    return ref;
   // }

   // /**
   //  * 多个数据相减处理。
   //  *
   //  * @param value1 数据1
   //  * @param value2 数据2
   //  * @return 向量
   //  */
   // public subVectors(value1: Value2, value2: Value2): Vector2 {
   //    this.x = value1.x - value2.x;
   //    this.y = value1.y - value2.y;
   //    return this;
   // }

   // /**
   //  * 相减出新的向量 内容1-内容2。
   //  *
   //  * @param value1 内容1
   //  * @param value2 内容2
   //  * @param ref
   //  * @return 向量
   //  */
   // public static subVector(value1: Value2, value2: Value2, ref?: Vector2): Vector2 {
   //    ref = ref || new Vector2();
   //    ref.x = value1.x - value2.x;
   //    ref.y = value1.y - value2.y;
   //    return ref;
   // }

   // /**
   //  * 数据相乘处理。
   //  *
   //  * @param value 数据
   //  * @return 向量
   //  */
   // public multiplyScalar(value: number): Vector2 {
   //    AssertUtil.debugNumber(value);
   //    this.x *= value;
   //    this.y *= value;
   //    return this;
   // }

   // /**
   //  * 相乘处理。
   //  *
   //  * @param value2 内容2
   //  * @param value 内容
   //  * @param ref
   //  */
   // public static multiplyScalarVector(value2: Value2, value: number, ref?: Vector2): Vector2 {
   //    AssertUtil.debugNumber(value);
   //    ref = ref || new Vector2();
   //    ref.x = value2.x * value;
   //    ref.y = value2.y * value;
   //    return ref;
   // }

   // /**
   //  * 单个数据相乘处理。
   //  *
   //  * @param value 数据
   //  * @return 向量
   //  */
   // public multiply(value: Value2): Vector2 {
   //    this.x *= value.x;
   //    this.y *= value.y;
   //    return this;
   // }

   // /**
   //  * 分量数据相乘处理。
   //  *
   //  * @param x X分量
   //  * @param y Y分量
   //  * @return 向量
   //  */
   // public multiplyValue(x: number, y: number): Vector2 {
   //    this.x *= x;
   //    this.y *= y;
   //    return this;
   // }

   // /**
   //  * 多个数据相乘处理。
   //  *
   //  * @param value1 数据1
   //  * @param value2 数据2
   //  * @return 向量
   //  */
   // public multiplyVectors(value1: Value2, value2: Value2): Vector2 {
   //    this.x = value1.x * value2.x;
   //    this.y = value1.y * value2.y;
   //    return this;
   // }

   // /**
   //  * 数据相除处理。
   //  *
   //  * @param value 数据
   //  * @return 向量
   //  */
   // public divideScalar(value: number): Vector2 {
   //    return this.multiplyScalar(1 / value);
   // }

   // /**
   //  * 单个数据相除处理。
   //  *
   //  * @param value 数据
   //  * @return 向量
   //  */
   // public divide(value: Value2): Vector2 {
   //    this.x /= value.x;
   //    this.y /= value.y;
   //    return this;
   // }

   // /**
   //  * 分量数据相除处理。
   //  *
   //  * @param x X分量
   //  * @param y Y分量
   //  * @return 向量
   //  */
   // public divideValue(x: number, y: number): Vector2 {
   //    this.x /= x;
   //    this.y /= y;
   //    return this;
   // }

   // /**
   //  * 获得正方向角度。(0 ~ 2PI)
   //  *
   //  * @return 角度
   //  */
   // public angle(): number {
   //    var angle = Math.atan2(this.y, this.x);
   //    if (angle < 0) {
   //       angle += MathUtil.PI2;
   //    }
   //    return angle;
   // }

   // /**
   //  * 获得长度。
   //  *
   //  * @return 长度
   //  */
   // public length(): number {
   //    return Math.sqrt(this.x * this.x + this.y * this.y);
   // }

   // /**
   //  * 获得平方长度。
   //  *
   //  * @return 长度
   //  */
   // public lengthSq(): number {
   //    return this.x * this.x + this.y * this.y;
   // }

   // /**
   //  * 获得平方长度。
   //  *
   //  * @return 长度
   //  */
   // public lengthSquared(): number {
   //    return this.x * this.x + this.y * this.y;
   // }

   // /**
   //  * 获得模长度。
   //  *
   //  * @return 长度
   //  */
   // public lengthManhattan(): number {
   //    return Math.abs(this.x) + Math.abs(this.y);
   // }

   // /**
   //  * 取正。
   //  */
   // public abs(): Vector2 {
   //    this.x = Math.abs(this.x);
   //    this.y = Math.abs(this.y);
   //    return this;
   // }

   // /**
   //  * 设置长度。
   //  *
   //  * @param length 长度
   //  * @return 向量
   //  */
   // public setLength(length: number): Vector2 {
   //    var currentLength = this.length();
   //    if (currentLength != 0) {
   //       var rate = length / currentLength;
   //       this.multiplyScalar(rate);
   //    }
   //    return this;
   // }

   // /**
   //  * 获得到指定点的长度。
   //  *
   //  * @param value 数据
   //  * @return 长度
   //  */
   // public distanceTo(value: Vector2): number {
   //    return Math.sqrt(this.distanceToSquared(value));
   // }

   // /**
   //  * 获得到指定点的平放长度。
   //  *
   //  * @param value 数据
   //  * @return 长度
   //  */
   // public distanceToSquared(value: Value2): number {
   //    var dx = this.x - value.x;
   //    var dy = this.y - value.y;
   //    return dx * dx + dy * dy;
   // }

   // /**
   //  * 单位化处理。
   //  *
   //  * @return 向量
   //  */
   // public normalize(): Vector2 {
   //    var length = this.length();
   //    if (Math.abs(length) <= MathUtil.EPSILON) {
   //       return this.set(0, 0);
   //    }
   //    return this.divideScalar(length);
   // }

   // /**
   //  * 计算取反的数据。
   //  *
   //  * @return 向量
   //  */
   // public negate(): Vector2 {
   //    this.x = -this.x;
   //    this.y = -this.y;
   //    return this;
   // }

   // /**
   //  * 计算向下取整的数据。
   //  *
   //  * @return 向量
   //  */
   // public floor(): Vector2 {
   //    this.x = Math.floor(this.x);
   //    this.y = Math.floor(this.y);
   //    return this;
   // }

   // /**
   //  * 计算向上取整的数据。
   //  *
   //  * @return 向量
   //  */
   // public ceil(): Vector2 {
   //    this.x = Math.ceil(this.x);
   //    this.y = Math.ceil(this.y);
   //    return this;
   // }

   // /**
   //  * 计算4舍5入的数据。
   //  *
   //  * @return 向量
   //  */
   // public round(): Vector2 {
   //    this.x = Math.round(this.x);
   //    this.y = Math.round(this.y);
   //    return this;
   // }

   // /**
   //  * 计算向0取整的数据。
   //  *
   //  * @return 向量
   //  */
   // public roundToZero(): Vector2 {
   //    this.x = (this.x < 0) ? Math.ceil(this.x) : Math.floor(this.x);
   //    this.y = (this.y < 0) ? Math.ceil(this.y) : Math.floor(this.y);
   //    return this;
   // }

   // /**
   //  * 设置最小数据。
   //  *
   //  * @return 向量
   //  */
   // public setMin(): Vector2 {
   //    this.x = Number.MIN_VALUE;
   //    this.y = Number.MIN_VALUE;
   //    return this;
   // }

   // /**
   //  * 计算最小数据。
   //  *
   //  * @param value 数据
   //  * @return 向量
   //  */
   // public min(value: Value2): void {
   //    this.x = Math.min(this.x, value.x);
   //    this.y = Math.min(this.y, value.y);
   // }

   // /**
   //  * 计算最小数据。
   //  *
   //  * @param x X分量
   //  * @param y Y分量
   //  * @return 向量
   //  */
   // public minValue(x: number, y: number): void {
   //    this.x = Math.min(this.x, x);
   //    this.y = Math.min(this.y, y);
   // }

   // /**
   //  * 设置最大数据。
   //  *
   //  * @return 向量
   //  */
   // public setMax(): void {
   //    this.x = Number.MAX_VALUE;
   //    this.y = Number.MAX_VALUE;
   // }

   // /**
   //  * 计算最大数据。
   //  *
   //  * @param value 数据
   //  * @return 向量
   //  */
   // public max(value: Value2): void {
   //    this.x = Math.max(this.x, value.x);
   //    this.y = Math.max(this.y, value.y);
   // }

   // /**
   //  * 计算最大数据。
   //  *
   //  * @param x X分量
   //  * @param y Y分量
   //  * @return 向量
   //  */
   // public maxValue(x: number, y: number): void {
   //    this.x = Math.max(this.x, x);
   //    this.y = Math.max(this.y, y);
   // }

   // /**
   //  * 计算最小和最大之间数据。
   //  *
   //  * @param min 最小数据
   //  * @param max 最大数据
   //  * @return 向量
   //  */
   // public clamp(min: Value2, max: Value2): Vector2 {
   //    this.x = Math.max(min.x, Math.min(max.x, this.x));
   //    this.y = Math.max(min.y, Math.min(max.y, this.y));
   //    return this;
   // }

   // /**
   //  * 计算最小和最大之间数据。
   //  *
   //  * @param min 最小数据
   //  * @param max 最大数据
   //  * @return 向量
   //  */
   // public clampScalar(min: number, max: number): Vector2 {
   //    this.x = Math.max(min, Math.min(max, this.x));
   //    this.y = Math.max(min, Math.min(max, this.y));
   //    return this;
   // }

   // /**
   //  * 计算最小和最大之间长度。
   //  *
   //  * @param min 最小数据
   //  * @param max 最大数据
   //  * @return 向量
   //  */
   // public clampLength(min: number, max: number): Vector2 {
   //    var length = this.length();
   //    var rate = Math.max(min, Math.min(max, length)) / length;
   //    this.multiplyScalar(rate);
   //    return this;
   // }

   // /**
   //  * 计算点积处理。
   //  *
   //  * @param value 数据
   //  * @return 数据
   //  */
   // public dot(value: Value2): number {
   //    return this.x * value.x + this.y * value.y;
   // }

   // /**
   //  * 计算插值处理。
   //  *
   //  * @param value 数据
   //  * @param rate 比率
   //  * @return 向量
   //  */
   // public lerp(value: Value2, rate: number): Vector2 {
   //    this.x += (value.x - this.x) * rate;
   //    this.y += (value.y - this.y) * rate;
   //    return this;
   // }

   // /**
   //  * 计算插值处理。
   //  *
   //  * @param value1 数据1
   //  * @param value2 数据2
   //  * @param rate 比率
   //  * @return 向量
   //  */
   // public lerpVectors(value1: Vector2, value2: Vector2, rate: number): Vector2 {
   //    this.subVectors(value2, value1);
   //    this.multiplyScalar(rate);
   //    this.add(value1);
   //    return this;
   // }

   // /**
   //  * 绕原点正向旋转弧度。
   //  *
   //  * @param rad 弧度
   //  * @return 向量
   //  */
   // public rotate(rad: number): Vector2 {
   //    var sin = Math.sin(rad);
   //    var cos = Math.cos(rad);
   //    var x = this.x;
   //    var y = this.y;
   //    this.x = x * cos - y * sin;
   //    this.y = x * sin + y * cos;
   //    return this;
   // }

   // /**
   //  * 绕原点正向旋转角度。
   //  *
   //  * @param angle 角度
   //  * @return 向量
   //  */
   // public rotateAngle(angle: number): Vector2 {
   //    var rad = MathUtil.degToRad(angle);
   //    return this.rotate(rad);
   // }

   // /**
   //  * 绕指定中心点正向旋转弧度。
   //  *
   //  * @param center 中心
   //  * @param rad 弧度
   //  * @return 向量
   //  */
   // public rotateAround(center: Value2, rad: number): Vector2 {
   //    var sin = Math.sin(rad);
   //    var cos = Math.cos(rad);
   //    var x = this.x - center.x;
   //    var y = this.y - center.y;
   //    this.x = x * cos - y * sin + center.x;
   //    this.y = x * sin + y * cos + center.y;
   //    return this;
   // }

   // /**
   //  * 绕指定中心点正向旋转角度。
   //  *
   //  * @param center 中心
   //  * @param angle 角度
   //  * @return 向量
   //  */
   // public rotateAroundAngle(center: Value2, angle: number): Vector2 {
   //    var rad = MathUtil.degToRad(angle);
   //    return this.rotateAround(center, rad);
   // }

   // /**
   //  * to3d。
   //  *
   //  * @return 向量
   //  */
   // public to3d(): Vector3 {
   //    return new Vector3(this.x, this.y, 0);
   // }

   // /**
   //  * 根据数据获得对象。
   //  *
   //  * @param value1 数据1
   //  * @param value2 数据2
   //  * @return 向量
   //  */
   // public from(value1?: any, value2?: any): Vector2 {
   //    var x = null;
   //    var y = null;
   //    var count = arguments.length;
   //    if (count == 1) {
   //       var value = arguments[0];
   //       if (Array.isArray(value)) {
   //          x = value[0];
   //          y = value[1];
   //       } else {
   //          x = value.x;
   //          y = value.y;
   //       }
   //    } else if (count == 2) {
   //       x = arguments[0];
   //       y = arguments[1];
   //    }
   //    AssertUtil.debugNumber(x, y);
   //    this.x = x;
   //    this.y = y;
   //    return this;
   // }

   // /**
   //  * 从数组中获得数据。
   //  *
   //  * @param array 数组
   //  * @param offset 位置
   //  * @return 向量
   //  */
   // public fromArray(array: Array<number>, offset: number = 0): Vector2 {
   //    this.x = array[offset];
   //    this.y = array[offset + 1];
   //    return this;
   // }

   // // /**
   // //  * 从属性流中获得数据。
   // //  *
   // //  * @param attribute 数组
   // //  * @param index 索引
   // //  * @param offset 位置
   // //  * @return 向量
   // //  */
   // // public fromAttribute(attribute, index: number, offset: number = 0) {
   // //    var position = index * attribute.itemSize + offset;
   // //    this.x = attribute.array[position];
   // //    this.y = attribute.array[position + 1];
   // //    return this;
   // // }
   // /**
   //  * 设置数据到数组中。
   //  *
   //  * @param array 数组
   //  * @param offset 位置
   //  * @return 数组
   //  */
   // public toArray(array?: Array<number>, offset: number = 0): Array<number> {
   //    if (array == null) {
   //       array = new Array<number>();
   //    }
   //    array[offset] = this.x;
   //    array[offset + 1] = this.y;
   //    return array;
   // }

   // /**
   //  * 序列化数据到输出流里。
   //  *
   //  * @param output 数据流
   //  * @param dataCd 数据类型
   //  * @return 数组
   //  */
   // public serialize(output: DataStream, dataCd: DataTypeEnum = DataTypeEnum.Float64): void {
   //    switch (dataCd) {
   //       case DataTypeEnum.Int32:
   //          output.writeInt32(this.x);
   //          output.writeInt32(this.y);
   //          break;
   //       case DataTypeEnum.Float32:
   //          output.writeFloat32(this.x);
   //          output.writeFloat32(this.y);
   //          break;
   //       case DataTypeEnum.Float64:
   //          output.writeFloat64(this.x);
   //          output.writeFloat64(this.y);
   //          break;
   //       default:
   //          throw new Fatal(this, 'Serialize invalid.');
   //    }
   // }

   // /**
   //  * 从输入流里反序列化数据。
   //  *
   //  * @param input 数据流
   //  * @param dataCd 数据类型
   //  */
   // public unserialize(input: DataStream, dataCd: DataTypeEnum = DataTypeEnum.Float64): void {
   //    switch (dataCd) {
   //       case DataTypeEnum.Int32:
   //          this.x = input.readInt32();
   //          this.y = input.readInt32();
   //          break;
   //       case DataTypeEnum.Float32:
   //          this.x = input.readFloat32();
   //          this.y = input.readFloat32();
   //          break;
   //       case DataTypeEnum.Float64:
   //          this.x = input.readFloat64();
   //          this.y = input.readFloat64();
   //          break;
   //       default:
   //          throw new Fatal(this, 'Unserialize invalid.');
   //    }
   // }

   // /**
   //  * 解析字符串。
   //  *
   //  * @param source 字符串
   //  * @return 向量
   //  */
   // public parse(source: string): Vector2 {
   //    var items = source.split(',');
   //    if (items.length == 2) {
   //       this.x = parseFloat(items[0]);
   //       this.y = parseFloat(items[1]);
   //    } else {
   //       throw new Fatal(this, "Parse value failure. (source={1})", source);
   //    }
   //    AssertUtil.debugNumber(this.x, this.y);
   //    return this;
   // }

   // /**
   //  * 格式化为字符串。
   //  *
   //  * @param precision 精度
   //  * @return 字符串
   //  */
   // public format(precision: number = MathUtil.PRECISION): string {
   //    var x = Float32Util.round(this.x, precision);
   //    var y = Float32Util.round(this.y, precision);
   //    return x + ',' + y;
   // }

   // /**
   //  * 获得字符串。
   //  *
   //  * @return 字符串
   //  */
   // public toString(): string {
   //    return this.x + ',' + this.y;
   // }

   // /**
   //  * 重置数据。
   //  *
   //  * @certify 220606
   //  * @return 向量
   //  */
   // public reset(): Vector2 {
   //    return this.set(0, 0);
   // }

   // /**
   //  * 释放内容。
   //  *
   //  * @certify 210926
   //  */
   // public free(): void {
   //    this.x = 0;
   //    this.y = 0;
   // }

   // /**
   //  * 克隆当前数据。
   //  *
   //  * @param type 类型
   //  * @return 向量
   //  */
   // public clone(type?: Function): Vector2 {
   //    var constructor = type || (this as any).constructor;
   //    return new constructor(this.x, this.y);
   //    // return new (this as any).constructor(this.x, this.y);
   // }

   // /**
   //  * 释放处理。
   //  */
   // public dispose(): void {
   //    this.x = null;
   //    this.y = null;
   // }
   // /** 原点 */
   // public static Origin = new Vector2(0, 0);
   // /** X轴 */
   // public static AxisX = new Vector2(1, 0);
   // /** Y轴 */
   // public static AxisY = new Vector2(0, 1);
   // /** -X轴 */
   // public static AxisNX = new Vector2(-1, 0);
   // /** -Y轴 */
   // public static AxisNY = new Vector2(0, -1);

   // /**
   //  * 根据数据获得对象。
   //  *
   //  * @param value1 数据1
   //  * @param value2 数据2
   //  * @return 向量
   //  */
   // public static from(value1?: any, value2?: any): Vector2 {
   //    var x = null;
   //    var y = null;
   //    var count = arguments.length;
   //    if (count == 1) {
   //       var value = arguments[0];
   //       if (Array.isArray(value)) {
   //          x = value[0];
   //          y = value[1];
   //       } else {
   //          x = value.x;
   //          y = value.y;
   //       }
   //    } else if (count == 2) {
   //       x = arguments[0];
   //       y = arguments[1];
   //    }
   //    AssertUtil.debugNumber(x, y);
   //    return new Vector2(x, y);
   // }

   // /**
   //  * 从UVW维度构造二维向量。
   //  *
   //  * @param u U维度
   //  * @param x X分量
   //  * @param v V维度
   //  * @param y Y分量
   //  * @return 向量
   //  */
   // public static fromUv(u: string, x: number, v: string, y: number): Vector2 {
   //    var value = new Vector2();
   //    value[u] = x;
   //    value[v] = y;
   //    return value;
   // }

   // /**
   //  * 判断是否为0。
   //  *
   //  * @param value 数据
   //  * @param tolerance 容差
   //  * @return 是否为0
   //  */
   // public static isZero(value: Value2, tolerance: number = MathUtil.TOLERANCE): boolean {
   //    if (value == null) {
   //       return false;
   //    }
   //    var ex = MathUtil.isZero(value.x, tolerance);
   //    var ey = MathUtil.isZero(value.y, tolerance);
   //    return ex && ey;
   // }

   // /**
   //  * 判断是否相等。
   //  *
   //  * @param value1 数据1
   //  * @param value2 数据2
   //  * @return 是否相等
   //  */
   // public static equals(value1: Value2, value2: Value2): boolean {
   //    if (value1 == value2) {
   //       return true;
   //    }
   //    if ((value1 == null) || (value2 == null)) {
   //       return false;
   //    }
   //    var ex = (value1.x == value2.x);
   //    var ey = (value1.y == value2.y);
   //    return ex && ey;
   // }

   // /**
   //  * 判断是否近似相等。
   //  *
   //  * @param value1 数据1
   //  * @param value2 数据2
   //  * @param tolerance 容差
   //  * @return 是否相等
   //  */
   // public static nearlyEquals(value1: Value2, value2: Value2, tolerance: number = MathUtil.TOLERANCE): boolean {
   //    if (value1 == value2) {
   //       return true;
   //    }
   //    if ((value1 == null) || (value2 == null)) {
   //       return false;
   //    }
   //    var ex = MathUtil.nearlyEquals(value1.x, value2.x, tolerance);
   //    var ey = MathUtil.nearlyEquals(value1.y, value2.y, tolerance);
   //    return ex && ey;
   // }

   // /**
   //  * 从集合中查找是否找到近似相等的点。
   //  *
   //  * @param points 点集合
   //  * @param point 点
   //  * @return 是否存在
   //  */
   // public static constains(points: Array<Value2>, point: Value2): boolean {
   //    var count = points.length;
   //    for (var i = 0; i < count; i++) {
   //       var value = points[i];
   //       if (this.equals(value, point)) {
   //          return true;
   //       }
   //    }
   // }

   // /**
   //  * 从集合中查找是否找到近似相等的点。
   //  *
   //  * @param points 点集合
   //  * @param point 点
   //  * @param tolerance 容差
   //  * @return 是否存在
   //  */
   // public static nearlyConstains(points: Array<Value2>, point: Value2, tolerance: number = MathUtil.TOLERANCE): boolean {
   //    var count = points.length;
   //    for (var i = 0; i < count; i++) {
   //       var value = points[i];
   //       if (Vector2.nearlyEquals(value, point, tolerance)) {
   //          return true;
   //       }
   //    }
   // }

   // /**
   //  * 从集合中找到近似相等的点。
   //  *
   //  * @param points 点集合
   //  * @param point 点
   //  * @param tolerance 容差
   //  * @return 近似点
   //  */
   // public static nearlyFind(points: Array<Value2>, point: Value2, tolerance: number = MathUtil.TOLERANCE): Value2 {
   //    var count = points.length;
   //    for (var i = 0; i < count; i++) {
   //       var value = points[i];
   //       if (Vector2.nearlyEquals(value, point, tolerance)) {
   //          return value;
   //       }
   //    }
   // }

   // /**
   //  * 从集合中过滤近似相等的点集合。
   //  *
   //  * @param points 点集合
   //  * @param point 点
   //  * @param tolerance 容差
   //  * @param targets 目标集合
   //  * @return 近似点集合
   //  */
   // public static nearlyFilter(points: Array<Value2>, point: Value2, tolerance: number = MathUtil.TOLERANCE, targets?: Array<Value2>): Array<Value2> {
   //    var result = targets || new Array<Value2>();
   //    var count = points.length;
   //    for (var i = 0; i < count; i++) {
   //       var value = points[i];
   //       if (Vector2.nearlyEquals(value, point, tolerance)) {
   //          result.push(value);
   //       }
   //    }
   //    return result;
   // }

   // /**
   //  * 从集合中过滤近似相等的点集合。
   //  *
   //  * @param values
   //  * @param sources
   //  * @param tolerance 容差
   //  * @param targets 目标集合
   //  * @return 近似点集合
   //  */
   // public static nearlyFilterArray(values: Array<Value2>, sources: Array<Value2>, tolerance: number = MathUtil.TOLERANCE, targets?: Array<Value2>): Array<Value2> {
   //    var result = targets || new Array<Value2>();
   //    var count = values.length;
   //    for (var i = 0; i < count; i++) {
   //       var value = values[i];
   //       var find = Vector2.nearlyFind(sources, value, tolerance);
   //       if (find) {
   //          result.push(find);
   //       }
   //    }
   //    return result;
   // }

   // /**
   //  * 多个数据相加处理。
   //  *
   //  * @param value1 数据1
   //  * @param value2 数据2
   //  * @param target 目标
   //  * @return 向量
   //  */
   // public static addVectors(value1: Value2, value2: Value2, target?: Vector2): Vector2 {
   //    var x = value1.x + value2.x;
   //    var y = value1.y + value2.y;
   //    var result = target || new Vector2();
   //    result.set(x, y);
   //    return result;
   // }

   // /**
   //  * 数组整体和向量相加处理。
   //  *
   //  * @param array 数组
   //  * @param value 数据
   //  */
   // public static addArrayVector(array: Array<Value2>, value: Value2): void {
   //    var count = array.length;
   //    for (var i = 0; i < count; i++) {
   //       var item = array[i];
   //       item.x += value.x;
   //       item.y += value.y;
   //    }
   // }

   // /**
   //  * 数组整体和向量相加处理。
   //  *
   //  * @param array 数组
   //  * @param x x分量
   //  * @param y y分量
   //  */
   // public static addArrayValue(array: Array<Value2>, x: number, y: number): void {
   //    var count = array.length;
   //    for (var i = 0; i < count; i++) {
   //       var item = array[i];
   //       item.x += x;
   //       item.y += y;
   //    }
   // }

   // /**
   //  * 多个数据相减处理。
   //  *
   //  * @param value1 数据1
   //  * @param value2 数据2
   //  * @param target 目标
   //  * @return 向量
   //  */
   // public static subVectors(value1: Value2, value2: Value2, target?: Vector2): Vector2 {
   //    var x = value1.x - value2.x;
   //    var y = value1.y - value2.y;
   //    var result = target || new Vector2();
   //    result.set(x, y);
   //    return result;
   // }

   // /**
   //  * 数据相乘处理。
   //  *
   //  * @param vectors 数据集合
   //  * @param scale
   //  */
   // public static multiplyScalar(vectors: Value2 | Array<Value2>, scale: number): void {
   //    if (Array.isArray(vectors)) {
   //       var count = vectors.length;
   //       for (var i = 0; i < count; i++) {
   //          var vector = vectors[i];
   //          vector.x *= scale;
   //          vector.y *= scale;
   //       }
   //    } else {
   //       vectors.x *= scale;
   //       vectors.y *= scale;
   //    }
   // }

   // /**
   //  * 数据相乘处理。
   //  *
   //  * @param vectors 数据集合
   //  * @param value 数据
   //  */
   // public static multiply(vectors: Value2 | Array<Value2>, value: Value2): void {
   //    if (Array.isArray(vectors)) {
   //       var count = vectors.length;
   //       for (var i = 0; i < count; i++) {
   //          var vector = vectors[i];
   //          vector.x *= value.x;
   //          vector.y *= value.y;
   //       }
   //    } else {
   //       vectors.x *= value.x;
   //       vectors.y *= value.y;
   //    }
   // }

   // /**
   //  * 获得两点之间点积。
   //  *
   //  * @param value1 数据1
   //  * @param value2 数据2
   //  * @return 点积
   //  */
   // public static dot(value1: Value2, value2: Value2): number {
   //    return value1.x * value2.x + value1.y * value2.y;
   // }

   // /**
   //  * 获得两点之间点积。
   //  *
   //  * @param x1 数据1的X分量
   //  * @param y1 数据1的Y分量
   //  * @param x2 数据2的X分量
   //  * @param y2 数据2的Y分量
   //  * @return 点积
   //  */
   // public static dotValue(x1: number, y1: number, x2: number, y2: number): number {
   //    return x1 * x2 + y1 * y2;
   // }

   // /**
   //  * 获得两点之间距离。
   //  *
   //  * @param point1 开始点
   //  * @param point2 结束点
   //  * @return 距离
   //  */
   // public static distance(point1: Value2, point2: Value2): number {
   //    var cx = point2.x - point1.x;
   //    var cy = point2.y - point1.y;
   //    return Math.sqrt(cx * cx + cy * cy);
   // }

   // /**
   //  * 获得两点之间距离。
   //  *
   //  * @param x1 开始点X坐标
   //  * @param y1 开始点Y坐标
   //  * @param x2 结束点X坐标
   //  * @param y2 结束点Y坐标
   //  * @return 距离
   //  */
   // public static distanceValue(x1: number, y1: number, x2: number, y2: number): number {
   //    AssertUtil.debugNumber(x1, y1, x2, y2);
   //    var cx = x1 - x2;
   //    var cy = y1 - y2;
   //    return Math.sqrt(cx * cx + cy * cy);
   // }

   // /**
   //  * 获得方向。
   //  *
   //  * @param point1 开始点
   //  * @param point2 结束点
   //  * @param target 目标
   //  * @return 方向
   //  */
   // public static direction(point1: Value2, point2: Value2, target?: Vector2): Vector2 {
   //    AssertUtil.debugNotNull(point1, point2);
   //    var x = point2.x - point1.x;
   //    var y = point2.y - point1.y;
   //    var direction = target || new Vector2();
   //    direction.set(x, y);
   //    direction.normalize();
   //    return direction;
   // }

   // /**
   //  * 获得方向角。
   //  *
   //  * @param from 开始点
   //  * @param to 结束点
   //  * @return 方向角
   //  */
   // public static rotation(from: Value2, to: Value2): number {
   //    var x = to.x - from.x;
   //    var y = to.y - from.y;
   //    return Math.atan2(y, x);
   // }

   // /**
   //  * 获得平方长度。
   //  *
   //  * @param x x分量
   //  * @param y y分量
   //  * @return 长度
   //  */
   // public static lengthSquared(x: number, y: number): number {
   //    return x * x + y * y;
   // }

   // /**
   //  * 计算插值处理。
   //  *
   //  * @param value1 内容1
   //  * @param value2 内容2
   //  * @param rate 比率
   //  * @return 向量
   //  */
   // public static lerp(value1: Value2, value2: Value2, rate: number): Vector2 {
   //    var x = MathUtil.lerp(value1.x, value2.x, rate);
   //    var y = MathUtil.lerp(value1.y, value2.y, rate);
   //    return new Vector2(x, y);
   // }

   // /**
   //  * 绕指定点旋转弧度。X右Y下坐标系看rad为正时是顺时针转。
   //  *
   //  * @param point 点
   //  * @param rad 弧度
   //  * @param target 目标
   //  * @return 向量
   //  */
   // public static rotate(point: Vector2, rad: number, target?: Vector2): Vector2 {
   //    var vcos = Math.cos(rad);
   //    var vsin = Math.sin(rad);
   //    var x = point.x * vcos - point.y * vsin;
   //    var y = point.x * vsin + point.y * vcos;
   //    var result = target || new Vector2();
   //    result.set(x, y);
   //    return result;
   // }

   // /**
   //  * 绕指定点旋转角度。
   //  *
   //  * @param point 点
   //  * @param angle 角度
   //  * @param target 目标
   //  * @return 向量
   //  */
   // public static rotateAngle(point: Vector2, angle: number, target?: Vector2): Vector2 {
   //    var rad = MathUtil.degToRad(angle);
   //    return Vector2.rotate(point, rad, target);
   // }

   // /**
   //  * 绕指定点旋转弧度。
   //  *
   //  * @param center 旋转中心点
   //  * @param point 目标点
   //  * @param rad 弧度
   //  * @param target 目标
   //  * @return 向量
   //  */
   // public static rotateAroundPoint(center: Value2, point: Value2, rad: number, target?: Vector2): Vector2 {
   //    var sub = Vector2.subVectors(point, center, target);
   //    return sub.rotate(rad).add(center);
   // }

   // /**
   //  * 绕指定点旋转角度。
   //  *
   //  * @param center 旋转中心点
   //  * @param point 目标点
   //  * @param angle 角度
   //  * @param target 目标
   //  * @return 向量
   //  */
   // public static rotateAroundPointAngle(center: Value2, point: Value2, angle: number, target?: Vector2): Vector2 {
   //    var rad = MathUtil.degToRad(angle);
   //    return Vector2.rotateAroundPoint(center, point, rad, target);
   // }

   // /**
   //  * 获得两个点的中心点。
   //  *
   //  * @param point1 点1
   //  * @param point2 点2
   //  * @param target 目标
   //  * @return 中心点
   //  */
   // public static middle(point1: Value2, point2: Value2, target?: Vector2): Vector2 {
   //    var x = point1.x + point2.x;
   //    var y = point1.y + point2.y;
   //    var result = target || new Vector2();
   //    result.set(x * 0.5, y * 0.5);
   //    return result;
   // }

   // /**
   //  * 计算当前向量在方向上的投影向量。
   //  *
   //  * @param value 向量
   //  * @param target 目标
   //  * @return 向量
   //  */
   // public projectOnVector(value: Vector2, target?: Vector2): Vector2 {
   //    // 计算比率
   //    var dot = value.dot(this);
   //    var lengthSquared = value.lengthSquared();
   //    var scalar = dot / lengthSquared;
   //    // 计算向量
   //    var result = target || new Vector2();
   //    result.assign(value);
   //    result.multiplyScalar(scalar);
   //    return result;
   // }

   // /**
   //  * X坐标反转转换器。
   //  *
   //  * @param point 坐标
   //  * @param target 目标
   //  * @return 坐标
   //  */
   // public static flipXConverter(point: Vector2, target?: Vector2): Vector2 {
   //    var result = target || new Vector2();
   //    result.x = -point.x;
   //    result.y = point.y;
   //    return result;
   // }

   // /**
   //  * Y坐标反转转换器。
   //  *
   //  * @param point 坐标
   //  * @param target 目标
   //  * @return 坐标
   //  */
   // public static flipYConverter(point: Vector2, target?: Vector2): Vector2 {
   //    var result = target || new Vector2();
   //    result.x = point.x;
   //    result.y = -point.y;
   //    return result;
   // }

   // /**
   //  * 格式化为字符串。
   //  *
   //  * @param value 内容
   //  * @param precision 精度
   //  * @return 字符串
   //  */
   // public static format(value: Value2, precision: number = MathUtil.PRECISION): string {
   //    var x = Float32Util.trunc(value.x, precision);
   //    var y = Float32Util.trunc(value.y, precision);
   //    return x + ',' + y;
   // }

   // /**
   //  * 格式化为字符串。
   //  *
   //  * @param x X坐标
   //  * @param y Y坐标
   //  * @param precision 精度
   //  * @return 字符串
   //  */
   // public static formatValue(x: number, y: number, precision: number = MathUtil.PRECISION): string {
   //    var cx = Float32Util.trunc(x, precision);
   //    var cy = Float32Util.trunc(y, precision);
   //    return cx + ',' + cy;
   // }

   // /**
   //  * 克隆向量。
   //  *
   //  * @param value 内容
   //  * @return 向量
   //  */
   // public static clone(value: Value2): Vector2 {
   //    return new Vector2(value.x, value.y);
   // }

   // /**
   //  * 克隆当前数据。
   //  *
   //  * @param array 数组集合
   //  * @param scaleX
   //  * @param scaleY
   //  * @return 向量
   //  */
   // public static cloneArray(array: Array<Value2>, scaleX: number = 1, scaleY: number = 1): Array<Vector2> {
   //    var result = new Array<Vector2>();
   //    var count = array.length;
   //    for (var i = 0; i < count; i++) {
   //       var value = array[i];
   //       result[i] = new Vector2(value.x * scaleX, value.y * scaleY);
   //    }
   //    return result;
   // }

   // /**
   //  * 转为一般向量。
   //  *
   //  * @return 一般向量
   //  */
   // public toVectorN(): VectorN {
   //    var rerult = new VectorN();
   //    rerult.push(this.x);
   //    rerult.push(this.y);
   //    return rerult;
   // }

   // /**
   //  * 四维矩阵变换。
   //  *
   //  * @param matrix 矩阵
   //  * @return 向量
   //  */
   // public applyMatrix4(matrix: Matrix4): Vector2 {
   //    var x = this.x;
   //    var y = this.y;
   //    var e = matrix.elements;
   //    this.x = e[0] * x + e[4] * y + e[12];
   //    this.y = e[1] * x + e[5] * y + e[13];
   //    return this;
   // }
}
